/**
 * 模块名称
 */
export const moduleName = "platform";

/**
 * 全局插件列表
 */
let globalAddons: any[string] = {};

export const proto = "__proto__";

/**
* 类型(构造函数)
*/
export interface type<T> {
    new(): T
}

/** 获取对象类型 */
export function getType<T>(obj: T): type<T> {
    return <type<T>>obj.constructor;
}

/**
 * 字符串格式化
 * @param str 字符串
 * @param args 参数
 */
export function format(str: string, ...args: any[]) {
    return str.replace(/\{(\d+)\}/g, function (s, i) {
        return args[i];
    });
}

/**
* 新建Guid
*/
export function newGuid(): string {
    let guid = "{";
    for (let i = 1; i <= 32; i++) {
        let n = Math.floor(Math.random() * 16.0).toString(16);
        guid += n;
        if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
            guid += "-";

    }
    return guid + "}";
}

/**
 * 获取KEY的值
 * @param json 数据
 * @param key 关键字
 * @description 不区分KEY的大小写
 */
export function getJsonValueByKey(json: {}, key: string): any {
    for (let k in json) {
        if (k.compare(key)) {
            return json[k];
        }
    }
    return undefined;
}

/**
* 获取当前日期字符串（精确到日）
*/
export function getCurrentDateString(): string {
    let today = new Date();
    let timeString = today.getFullYear() + "/" + today.getMonth() + "/" + today.getDay();
    return timeString;
}

/**
* 获取当前时间字符串（精确到毫秒）
*/
export function getCurrentTimeString(): string {
    let today = new Date();
    return `${today.getFullYear()}/${today.getMonth()}/${today.getDay()} ${today.getHours()}:${today.getMinutes()}:${today.getSeconds()}.${today.getMilliseconds()}`;
}

/**
 * 日期工具类
 * @author chencx（陈楚溪）
 */
export class dateUtil {
    /**
     * 格式化，将 Date 转化为指定格式的String，
     * 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
     * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)。
     * 例子：
     * FormatDate().format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 
     * FormatDate().format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18 
     * @param fmt 格式化字符串，默认为"yyyy/MM/dd hh:mm:ss"
     * @param date 待格式化日期对象，默认为当前日期
     */
    static format(fmt: string = "yyyy/MM/dd hh:mm:ss", date: Date = new Date()): string {
        let o = {
            "M+": date.getMonth() + 1, //月份 
            "d+": date.getDate(), //日 
            "h+": date.getHours(), //小时 
            "m+": date.getMinutes(), //分 
            "s+": date.getSeconds(), //秒 
            "q+": Math.floor((date.getMonth() + 3) / 3), //季度 
            "S": date.getMilliseconds() //毫秒 
        };
        if (/(y+)/.test(fmt))
            fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (let k in o)
            if (new RegExp("(" + k + ")").test(fmt))
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        return fmt;
    }
    /**
     * 获取当前日期字符串（精确到日）
     */
    static getCurrentDateString(): string {
        let dateString = this.format("yyyy/MM/dd");
        return dateString;
    }
    /**
     * 获取当前时间字符串（精确到毫秒）
     */
    static getCurrentTimeString(): string {
        let timeString = this.format("yyyy/MM/dd hh:mm:ss:S")
        return timeString;
    }
}

export class proxy {
    /**
    * 创建透明代理
    * @param origionObject 原始对象
    * @param methodHandler 代理方法
    */
    static createTransparentProxy(origionObject: new () => any, methodHandler: (methodName: string, args: any[]) => any): any {
        let proxyObject = {};
        let proxyType = origionObject.prototype;
        let funcNameList: string[] = [];
        // 将函数名赋值到数组，进行闭包处理
        for (var func in proxyType) {
            var prop = proxyType[func];
            if (prop instanceof Function) {
                funcNameList.push(func);
            }
        }
        // 通过函数名数组定义代理的方法
        for (let funcName of funcNameList) {
            proxyObject[funcName] = (...proxyArgs: any[]): any => {
                return methodHandler(funcName, proxyArgs);
            }
        }

        return proxyObject;
    }

    /**
    * 在原对象上创建透明代理方法
    * @param origionObject 原始对象
    * @param methodHandler 代理方法
    */
    static buildTransparentProxyObject(destObject: Object, origionObject: type<any>, methodHandler: (methodName: string, args: any[]) => any) {
        let proxyType = origionObject.prototype;
        let funcNameList: string[] = [];
        let baseObj = new baseObject();

        // 将函数名赋值到数组，进行闭包处理
        for (var func in proxyType) {
            /** 只代理非baseObject类型中的方法 */
            if (!baseObj[func]) {
                var prop = proxyType[func];
                if (prop instanceof Function) {
                    funcNameList.push(func);
                }
            }
        }
        // 通过函数名数组定义代理的方法
        for (let funcName of funcNameList) {
            destObject[funcName] = (...proxyArgs: any[]): any => {
                return methodHandler(funcName, proxyArgs);
            }
        }
    }
}

export class reflect {
    /**
    * 指定类型
    * @param originObject 要指定类型的原始对象
    * @param targetType 目标类型
    */
    static assignType(originObject: any, targetType: Function) {
        let newMethod: any = targetType;
        originObject.__proto__ = newMethod.prototype;
        originObject.__proto__.constructor = newMethod;

        // 调用构造方法，并复制数据到原始对象，这种方法相对call来说，会复制装饰器修饰的方法
        let newObj = new newMethod();
        reflect.propertyCopy(originObject, newObj);

        // 调用事件
        if (originObject.onAssignedType) {
            originObject.onAssignedType();
        }
    }
    /**
    * 获取类名
    * @param objClass 对象类型
    */
    static getTypeFullName(objClass: any): string {
        let func: Function;
        if (objClass instanceof Function) {
            func = objClass;
        }
        else if (objClass && objClass.constructor) {
            func = objClass.constructor;
        }
        if (func) {
            let strFun = func.toString();
            let className = strFun.substr(0, strFun.indexOf('('));
            className = className.replace('function', '');
            className = className.replace(/(^\s*)|(\s*$)/ig, '');
            if (func.prototype.$module) {
                return func.prototype.$module + "." + className;
            } else {
                return className;
            }
        }
        if (objClass.name) {
            return objClass.name;
        }
        return typeof objClass;
    }

    /**
     * 属性赋值，将源对象的所有属性复制到目标对象
     * @param destObject 目标对象
     * @param srcObject 源对象
     * @param coverDefinedField 覆盖已经有数值的字段
     */
    static propertyCopy(destObject: Object, srcObject: Object, coverDefinedField: boolean = false): void {
        for (let property in srcObject) {
            // 只复制没有设置的属性
            if (coverDefinedField || !destObject[property]) {
                destObject[property] = srcObject[property];
            }
        }
    }

    /**
     * 判断对象是否属于某个类型
     * @param originObject 待判断的对象
     * @param objectType 对象类型
     */
    static isTypeOf<T>(originObject: any, objectType: type<T>): boolean {
        if (originObject.constructor == objectType) {
            return true;
        }

        if (!originObject.__proto__)
            return false;

        if (reflect.isTypeOf<T>(originObject.__proto__, objectType)) {
            return true;
        }

        return false;
    }
}


/**
 * 事件
 */
export class event<T>{
    /** 事件列表 */
    private handlers = [];
    /** 注册事件 */
    register(callback: T) {
        this.handlers.push(callback);
        return this;
    }
    /** 触发事件 */
    fire(args?: any) {
        for (let callback of this.handlers) {
            if (typeof callback === "function") {
                callback(args);
            }
        }
    }
    /** 是否存在事件 */
    have() {
        return this.handlers.length > 0;
    }
}


/**
* Json请求
*/
export interface remoteHeader {
    userToken?: userToken;
    userID?: string;
    transactionID?: string;
    password?: string;
}

// /**
// * 远程请求
// */
// export interface remoteRequest {
//     serviceName: string;
//     functionName: string;
//     header?: remoteHeader;
//     args?: any;
// }

/**
* 类型名称属性名
*/
export const typeNamePropertyName: string = "$type";

/**
* 基础插件对象:所有实体对象的基类，实现了ID，Name和Description，其中ID是对象的唯一标识，Name是对象的好记的名称，Description是对象的描述
*/
export interface addonObject {
    /** 类型名称，序列化/反序列化时用于保存类型的原型 */
    $type?: string;
    /** 工厂 */
    $factory?: proxyFactory;
    /** 元数据：模块/命名空间名称 */
    $module?: string;
    /** 元数据：插件名称 */
    $addonName?: string;
    /** 元数据：插件描述 */
    $addonDescription?: string;
    /** 扩展属性 */
    [id: string]: any

    /**
        * 事件：指定类型后
        */
    onAssignedType?(): void;
}

//******************** 装饰器 *********************
/**
 * 插件装饰器：用此装饰过的插件会将构造函数添加到插件类型列表中，便于检索
 * @param name 插件名称
 * @param description 插件描述
 */
export function addon(name: string, description?: string, moduleName?: string) {
    return function (target: any) {
        target.prototype.$module = moduleName;
        target.prototype.$addonName = name;
        target.prototype.$addonDescription = description;

        let fullName = reflect.getTypeFullName(target);
        log(`插件${fullName}加载成功.`);
        globalAddons[fullName] = target;
    };
}

//********************   实体对象   *********************
/**
 * 基础插件对象:所有实体对象的基类，实现了ID，Name和Description，其中ID是对象的唯一标识，Name是对象的好记的名称，Description是对象的描述
 */
@addon("基础插件对象",
    "所有实体对象的基类，实现了ID，Name和Description，其中ID是对象的唯一标识，Name是对象的好记的名称，Description是对象的描述",
    moduleName)
export class baseObject implements addonObject {
    /** 类型名称，序列化/反序列化时用于保存类型的原型 */
    $type?: string;
    /** 类型 */
    $constructor?: type<addonObject>;
    /**
     * 对象ID
     */
    $id?: string;
    /** 元数据：模块/命名空间名称 */
    $module?: string;
    /** 元数据：插件名称 */
    $addonName?: string;
    /** 元数据：插件描述 */
    $addonDescription?: string;
    /** 扩展属性 */
    [id: string]: any;
    /**
     * 事件：指定类型后
     */
    onAssignedType?(): void { }

    /**
     * 从Origion生成
     * @param origion 原始对象
     */
    from?(origion: any) {
        reflect.propertyCopy(origion, this);
    }
}

/**
 * 工厂
 */
export interface factory {
    /**
     * 获取值
     */
    getValue?(): any;
}

export function isFactory(obj: any): obj is factory {
    return (<factory>obj).getValue !== undefined;
}

/**
 * 获取对象
 * @param obj 对象，可能是实例或工厂
 */
export function getObject<T>(obj: T | factory): T {
    if (isFactory(obj)) {
        return obj.getValue();
    } else {
        return obj;
    }
}

/**
 * 代理工厂: 通过代理方式实现的工厂
 */
@addon("代理工厂",
    "通过代理方式实现的工厂",
    moduleName)
export class proxyFactory extends baseObject implements factory {
    /** 
     * 工厂的目标对象 
     */
    destType: baseObject;
    /**
     * 内部对象
     */
    protected innerObject?: any = {};

    constructor(objectType: type<any>) {
        super();
        if (objectType) {
            this.destType = new objectType();
        }
    }

    proxyMethod?(methodName: any, args: any): any {
        return this.innerObject[methodName].apply(args);
    }

    getValue?(): any {
        if (!this.innerObject) {
            this.innerObject = {};
        }

        /** 指定类型后建立代理对象 */
        proxy.buildTransparentProxyObject(this.innerObject, getType<any>(this.destType), (methodName: any, args: any) => {
            return this.proxyMethod(methodName, args);
        });
        return this.innerObject;
    }
}

/**
 * 对象工厂: 对象的直接引用
 */
@addon("对象工厂",
    "对象的直接引用",
    moduleName)
export class objectFactory extends baseObject implements factory {
    constructor(public objectReference?: any) {
        super();
    }

    getValue?(): any {
        return this.objectReference;
    }
}

/**
 * Json工厂: 通过JSONP字符串创建对象
 */
@addon("Json工厂",
    "通过JSONP字符串创建对象",
    moduleName)
export class jsonFactory extends baseObject implements factory {
    constructor(public jsonString?: string) {
        super();
    }

    getValue?(): any {
        if (!this.jsonString)
            return addonDeserialize(this.jsonString);
        return undefined;
    };
}

/**
 * 插件工厂：根据插件ID获取插件
 */
@addon("插件工厂",
    "根据插件ID加载插件的工厂",
    moduleName)
export class addonFactory extends baseObject implements factory {
    constructor(public rootObject?: any, public addonID?: string) {
        super();
    }

    getValue?(): any {
        if (!this.rootObject && !this.addonID)
            return findAddonByID(this.rootObject, this.addonID);
        return undefined;
    };
}

/**
 * 懒工厂
 */
@addon("懒工厂",
    "延迟加载工厂",
    moduleName)
export class lazyFactory<T> extends baseObject implements factory {
    /**
     * 构造方法
     * @param url url地址
     * @param objectName 对象名称 
     */
    constructor(public url?: string, public objectName?: string) {
        super();
    }

    getValue?(): any {
        let mod = require(`../../${this.url}`);
        return mod[this.objectName];
    };
}


/**
 * 根据插件ID查找插件
 * @param rootObject 根对象
 * @param addonID 插件ID
 */
export function findAddonByID(rootObject: any, addonID: string): any {
    if (rootObject.ID == addonID) {
        return rootObject
    }

    // 查找子属性
    for (let property in rootObject) {
        let childAddon = findAddonByID(rootObject[property], addonID);
        if (childAddon)
            return childAddon;
    }

    return undefined;
}

/**
* 将对象中的类型信息取出并更改对象的类型
* @param rootObject 待获取类型的对象
*/
export function fetchAddonProtoType(rootObject: Object): void {
    // 获取子属性的类型信息
    for (let property in rootObject) {
        let properyValue = rootObject[property];
        if (properyValue instanceof Object && !(properyValue instanceof Function)) {
            fetchAddonProtoType(properyValue);
        }
    }

    // 先通过$constructor获取类型
    let classType = rootObject.constructor;
    if (!classType || classType == Object) {
        // 然后通过$type获取类型
        let typeName = rootObject[typeNamePropertyName];
        if (typeName) {
            classType = getAddonTypeByFullName(typeName);
        }
    }
    if (classType) {
        reflect.assignType(rootObject, classType);
    }
}
/**
* 设置类型信息到对象中
* @param rootObject 待设置类型的对象
*/
export function setAddonTypeInfo(addonObject: Object): void {
    // 设置子属性的类型信息
    for (let property in addonObject) {
        let properyValue = addonObject[property];
        if (properyValue instanceof Object) {
            setAddonTypeInfo(properyValue);
        }
    }
    let typeName = reflect.getTypeFullName(addonObject);
    if (typeName != "Object" && typeName != "String") {
        addonObject[typeNamePropertyName] = typeName;
    }
}

/**
* 根据类型名称获取类型
* @param typeName 类型名称
*/
export function getAddonTypeByFullName(typeName: string): any {
    return globalAddons[typeName];
}

/**
* 插件序列化
* @param origion 待序列化的原始对象
*/
export function addonSerialize(origin: Object): string {
    setAddonTypeInfo(origin);
    return JSON.stringify(origin);
}

/**
    * 插件反序列化
    * @param jsonString json字符串
    */
export function addonDeserialize(jsonString: string): any {
    let result = JSON.parse(jsonString);
    fetchAddonProtoType(result);
    return result;
}

/**
    * 反序列化
    * @param classType 类型
    * @param jsonString json字符串
    */
export function addonDeserialize_T<T>(classType: type<T>, jsonString: string): T {
    let result: any = JSON.parse(jsonString);
    reflect.assignType(result, classType);
    return result;
}

/**
* 转换为字符串，如果是函数，获取函数脚本，如果是对象，获取Json
* @param origin
*/
export function toString(origin: any): string {
    if (origin instanceof Function) {
        return origin.toString();
    }
    return addonSerialize(origin);
}


/**
 * 日志记录 
 */
@addon("日志记录器", "日志记录器基类（可用于远程代理）", moduleName)
export class baseLogger extends baseObject {
    /**
     * 记录信息
     * @param date 日期
     * @param message 消息 
     * @param infoType 消息类型，可选的值：error: 错误；warning：警告；information：信息
     */
    log(date: Date, message: string, infoType: "error" | "warning" | "information" = "information"): void {

    }
}

@addon("日志服务",
    "记录普通信息和异常信息的服务",
    moduleName)
export class consoleLogger extends baseLogger {
    /**
     * 记录信息
     * @param date 日期
     * @param message 消息 
     * @param infoType 消息类型，可选的值：error: 错误；warning：警告；information：信息
     */
    log(date: Date, message: string, infoType: "error" | "warning" | "information" = "information"): void {
        logToConsole(date, message, infoType);
    }
}

/** 日志服务 */
export let serverLogger: baseLogger;
/** 日志服务 */
export let clientLogger: baseLogger = new consoleLogger();

/**
 * 记录错误到服务器
 * @param message 错误消息
 * @param infoType 消息类型，可选的值：error: 错误；warning：警告；information：信息
 */
export function logToServer(message: string, infoType: "error" | "warning" | "information" = "information") {
    if (serverLogger) {
        serverLogger.log(new Date(Date.now()), message, infoType);
    } else {
        clientLogger.log(new Date(Date.now()), `日志服务未设置，转发服务端日志：${message}`, infoType);
    }
}

/**
 * 记录错误到客户端
 * @param message 错误消息
 * @param infoType 消息类型，可选的值：error: 错误；warning：警告；information：信息
 */
export function log(message: string, infoType: "error" | "warning" | "information" = "information") {
    if (clientLogger) {
        clientLogger.log(new Date(Date.now()), message, infoType);
    } else {
        logToConsole(new Date(Date.now()), message, infoType);
    }
}

/**
 * 记录信息
 * @param date 日期
 * @param message 消息 
 * @param infoType 消息类型，可选的值：error: 错误；warning：警告；information：信息
 */
export function logToConsole(date: Date, message: string, infoType: "error" | "warning" | "information" = "information"): void {
    let dataString = `${date.toLocaleString()}`;
    if (infoType == "error") {
        console.error(`[${dataString} ${message}]`);
    } else if (infoType == "warning") {
        console.warn(`[${dataString} ${message}]`);
    }
    else {
        console.log(`[${dataString} ${message}]`);
    }
}


/**
 * 行状态
 */
export const dataRowState = {


    /**
     * 
     */
    detached: 'Detached',

    /**
     * 未更改
     */
    unchanged: 'Unchanged',

    /**
     * 增加
     */
    added: 'Added',

    /**
     * 已删除
     */
    deleted: 'Deleted',

    /**
     * 已修改
     */
    Modified: 'Modified'
};

/**
 * 表格信息类
 */
export class DataTableInfo {

    /**
     * 主键
     */
    keyField?: string[];


    /**
     * 表名
     */
    tableName?: string;

    /**
     * 所有列名
     */
    columnNames?: string[];

}


@addon("列", "用于类的名称类型", moduleName)
export class dataColumn extends baseObject {
    /** 字段名 */
    name?: string;
    /**  字段标题 */
    caption?: string;
    /** 字段类型 */
    type?: "string" | "number" | "date" | "boolean";
}



@addon("行", "数据行", moduleName)
export class dataRow extends baseObject {
    /**
     * 行属性
     */
    dataRowStatus: string;

    /**
     * 当前值
     */
    rowValues?: {};

    /**
     * 原始值
     */
    rowOriginalValue?: {};

    /**
     * 
     * @param status 设置行状态
     */
    setdataRowStatus(status: string) {
        this.dataRowStatus = status;
    }


}

/**
 * 字段
 */
@addon("字段", "用于容纳字段的名称、值等", moduleName)
export class dataField extends dataColumn {
    /** 字段值 */
    value?: any;
    /** 数据显示格式 */
    format?: string;
    /** 获取格式化值 */
    getFormatValue?() {
        if (this.format && this.value) {
            // 判断格式存在{0}
            if (this.format.search(/\{(\d+)\}/g) > 0) {
                return format(this.format, this.value);
            }
        }
    }
}

/**
 * 数据表
 */
@addon("数据表", "用于容纳二维数据的表格", moduleName)
export class dataTable extends baseObject {
    /**
     * 表名
     */
    name: string;
    /**
     * 列定义
     */
    columns?: dataColumn[string];
    /**
     * 主键
     */
    primaryKey?: string[];
    /**
     * 行定义
     */
    rows?: dataRow[];

    /**
     * 获取字段的值
     * @param rowIndex 行号
     * @param columnName 列名 
     */
    field?(rowIndex: number, columnName: string): any {
        return (this.rows[rowIndex].rowValues)[columnName];
    }

    /**
     * 添加列
     * @param column 列
     */
    addColumn?(column: dataColumn): void {
        if (!this.columns) {
            this.columns = {};
        }
        this.columns[column.name] = column;
    }

    /**
     * 移除列
     * @param columnName 列名
     */
    removeColumn?(columnName: string): void {
        delete this.columns[columnName];
    }

    /**
     * 清除列
     */
    clearColumns?(): void {
        delete this.columns;
    }

    /**
     * 清除数据
     */
    clearData?(): void {
        delete this.rows;
    }

    /**
     * 增加空行
     * @param count 增加的空行数
     */
    addRow(count: number): void {
        for (var i = 0; i < count; i++) {
            let itemrow = new dataRow();
            itemrow.rowValues = {};
            itemrow.rowOriginalValue = {};
            for (let key in this.columns) {
                itemrow.rowValues[key] = '';
                itemrow.rowOriginalValue[key] = '';
            }
            this.rows.push(itemrow);
        }
    }
}

@addon("数据集", "用于多个数据表格的数据集合", moduleName)
export class dataSet extends baseObject {
    /**
     * 数据表
     */
    tables: dataTable[string];

    /**
     * 添加表
     * @param table 列
     */
    addTable?(table: dataTable): void {
        this.tables[table.name] = table;
    }

    /**
     * 移除表
     * @param tableName 表名
     */
    removeTable?(tableName: string): void {
        delete this.tables[tableName];
    }

    /**
     * 清除表
     */
    clearTables?(): void {
        delete this.tables;
    }
}

/**
 * 服务基类
 */
@addon("服务基类", "服务基类", moduleName)
export class baseService extends baseObject {
    /**
     * 请求报文头
     */
    rqHeader: remoteHeader;
}

/**
 * 数据服务基类
 */
@addon("数据服务基类", "所有数据服务对象的基类（仅可用于异步工厂）", moduleName)
export class IDataService {
    /**
     * 
     * @param command 命令ID
     * @param paramValues 参数
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     */
    query(command: string, paramValues: {}, startIndex: number = 0, maxCount: number = 500): Promise<any> {
        return undefined;
    }


    /**
     *  查询数据最大条数
     * @param command 
     * @param paramValues 
     */
    queryCount(command: string, paramValues: {}): Promise<number> {
        return undefined;
    }

    /**
     * 更新表格
     * @param datatable 
     */
    updateTable(datatable: dataTable): Promise<number> {
        return undefined;
    }

    /**
     * 查询表格信息
     * @param tableName  表名
     */
    queryTableInfo(tableName: string): Promise<DataTableInfo> {
        return undefined;
    }
    /** 获取表结构 */
    getTableSchema(command: string): Promise<dataTable> {
        return undefined;
    }
}

/**
 * 数据获取器
 */
@addon("数据获取器", "数据获取器基类", moduleName)
export class baseDataFetcher extends baseObject {
    /**
     * 获取器名称
     */
    name?: string;
    /**
     * 查询
     * @param command 查询命令，可以是命令ID也可以是命令字符串
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     * @param paramValues 参数值
     */
    query?(paramValues: {}, startIndex: number = 0, maxCount: number = 500): Promise<dataTable> {
        return undefined;
    }
    /** 获取表结构 */
    getTableSchema?(): Promise<dataTable> {
        return undefined;
    }
}

/**
 * 数据源
 */
@addon("数据源", "所有提供数据的数据源的基类", moduleName)
export class baseDataSource extends baseObject {
    /** 数据源名称 */
    name?: string;
    /** 默认参数值 */
    defaultParamValues?: {};
    /** 自动查询时间间隔 */
    autoQueryInterval?: number;
    /** 是否需要自动查询 */
    autoQuery?: boolean = true;
    /**  数据视图 */
    views?: dataView;
    /** 查询事件:数据变化 */
    onQueryEvent?: event<(table: dataTable) => void>;
    /** 表结构初始化事件:数据变化 */
    onInitTableSchemaEvent?: event<(table: dataTable) => void>;
    /**
     * 分页参数（为了分页查询，存储查询的参数）
     */
    protected pageParamValues?: any;
    /** 数据源 */
    constructor() {
        super();
        // 初始化事件
        this.onQueryEvent = new event<(table: dataTable) => void>();
        this.onInitTableSchemaEvent = new event<(table: dataTable) => void>();
    }
    /**
     * [派生]执行查询
     * @param paramValues 查询参数
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     */
    onQuery?(paramValues?: any[string], startIndex: number = 0, maxCount: number = 500): Promise<any> {
        return undefined;
    }
    /** [派生]执行表结构初始化 */
    onInitTableSchema?(): Promise<any> {
        return undefined;
    }
    /**
     * 查询
     * @remark 手动查询,自动查询调用的查询方法
     * 数据变化通过事件返回
     */
    query?(paramValues?: any[string], startIndex: number = 0, maxCount: number = 500): Promise<any> {
        let realParamValues = {};
        if (this.defaultParamValues) {
            reflect.propertyCopy(realParamValues, this.defaultParamValues);
        }
        if (paramValues) {
            reflect.propertyCopy(realParamValues, paramValues);
        }
        this.pageParamValues = realParamValues;
        return this.onQuery(realParamValues, startIndex, maxCount)
            .then(table => {
                // 数据源获取的数据table的表名与数据源相同
                if (table) {
                    table.name = this.name;
                    // 触发事件
                    if (this.onQueryEvent.have) {
                        this.onQueryEvent.fire(table);
                    }
                }
            }).catch(error => {
                throw error;
            });
    }

    /**
     * 分页查询
     * @param startIndex 开始查询条数
     * @param maxCount 查询最大条数
     */
    pageQuery?(startIndex: number, maxCount: number): Promise<any> {
        return this.onQuery(this.pageParamValues, startIndex, maxCount);
    }

    /** 表结构初始化 */
    initTableSchema?(): Promise<any> {
        return this.onInitTableSchema()
            .then(table => {
                if (table)
                    table.name = this.name;
                if (this.onInitTableSchemaEvent.have) {
                    this.onInitTableSchemaEvent.fire(table);
                }
            }).catch(error => {
                throw error;
            });
    }
    initQuery?(): Promise<any> {
        return this.onQuery({})
            .then(table => {
                if (table) {
                    table.name = this.name;
                }
                return table;
            });
    }
}


/**
 * 查询数据源
 */
@addon("查询数据源", "从数据服务获取器查询的数据源", moduleName)
export class dataQuerySource extends baseDataSource {
    /** 数据获取器集合 */
    fetcher?: baseDataFetcher;
    /** 参数名列表
     * @remark 如:id:code */
    paramKeyList?: any[string];
    /**
     * 执行查询
     * @param paramValues 查询参数
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     */
    onQuery?(paramValues?: any[string], startIndex: number = 0, maxCount: number = 500): Promise<any> {
        if (!this.fetcher) throw new Error('数据获取器不能为空');
        let realParamValues = this.getParamValues(paramValues);
        return this.fetcher.query(realParamValues, startIndex, maxCount);
    }
    onInitTableSchema?() {
        if (!this.fetcher) throw new Error('数据获取器不能为空');
        return this.fetcher.getTableSchema();
    }
    /**
     * 获取参数
     * @param paramValues 查询参数
     */
    getParamValues(paramValues?: any[string]) {
        if (this.paramKeyList) {
            let params = {};
            for (let key in this.paramKeyList) {
                let name = this.paramKeyList[key];
                if (paramValues[name]) {
                    params[key] = paramValues[name];
                }
            }
            return params;
        }
        return paramValues;
    }
}

/**
 * 数据视图
 */
@addon("数据视图", "通过字符串过滤语句过滤客服端数据源", moduleName)
export class dataView extends baseObject {
    /**
     * 过滤字符串
     * @remark 可以通过eval运行的字符代码
     * 例如:row.sex == '男' && row.age > 99
     */
    filterString?: string;
    /** 
     * 数据源名称
     * @remark 指定报表模块显示的数据来源
     */
    dataSourceName?: string;
    /** 事件:数据变化 */
    onQueryEvent?: event<(table: dataTable) => void>;
    /** 表结构初始化事件:数据变化 */
    onInitTableSchemaEvent?: event<(table: dataTable) => void>;
    constructor() {
        super();
        // 初始化事件
        this.onQueryEvent = new event<(table: dataTable) => void>();
        this.onInitTableSchemaEvent = new event<(table: dataTable) => void>();
    }
    /** 数据变化处理 */
    onQuery?(table: dataTable) {
        if (table && this.dataSourceName) {
            if (table.name !== this.dataSourceName)
                return;
            let targetTable = new dataTable();
            if (this.filterString) {
                targetTable.name = table.name ? table.name : undefined;
                targetTable.columns = table.columns ? table.columns : undefined;
                targetTable.rows = [];
                for (let dr of table.rows) {
                    let r = new dataRow();
                    let row = dr.rowValues;
                    let filte = eval(this.filterString);
                    if (filte) {
                        r.rowValues = row;
                        targetTable.rows.push(r);
                    }
                }
            } else {
                targetTable = table;
            }
            // 触发事件变化
            if (this.onQueryEvent.have) {
                this.onQueryEvent.fire(targetTable);
            }
        }
    }
    /** 表结构初始化事件处理 */
    onInitTableSchema?(table: dataTable) {
        if (table && this.dataSourceName) {
            if (table.name !== this.dataSourceName)
                return;
            if (this.onInitTableSchemaEvent.have) {
                this.onInitTableSchemaEvent.fire(table);
            }
        }
    }
}


/**
 * 角色
 */
export class role {
    /**
     * 角色ID
     */
    id: string;

    /**
     * 角色名称
     */
    name: string;

    /**
     * 机构ID
     */
    orgID: string;
}

/**
 * 用户信息
 */
export class userInfo {
    /**
     * 用户ID
     */
    userId: string;
    /**
     * 登录输入的帐号
     */
    logingAccount: string;
    /**
     * 手机号码
     */
    mobile: string;
    /**
     * 密码
     */
    password: string;
    /**
     * 用户名
     */
    name: string;
    /**
     * 登录类型
     */
    loginType: string;
    /**
     * 最后操作时间
     */
    lastOptTime: Date;
    /**
     * 登录状态
     */
    status: string;
    /**
     * 角色列表
     */
    roles: role[] = [];
    /**
     * 额外信息
     */
    extrainfo: Object;
}
/**
* 用户令牌
*/
export class userToken {
    /**
     * 用户信息
     */
    userinfo: userInfo;


    /**
    * 用户名
    */
    name: string;
    /**
    * 密码，经过MD5运算
    */
    password: string;
}

/**
* 当前用户
*/
export let currentUser: userToken;


export class feature extends baseObject {
    /**
     * 控制者
     */
    owner?: string;
    /**
     * 控制者类型
     */
    ownerType?: string;
    /**
     * 控制内容
     */
    content?: string;
    /**
     * 效果
     */
    effect?: string;
    /**
     * 目标类型
     */
    targetType?: string;
    /**
     * 级别
     */
    level?: number;
}

/**
 * 基础特性控制器
 */
export class baseFeatureController {
    /**
     * 特性列表
     */
    features?: feature[];
    /**
     * 默认特性
     */
    defaultFeature?: feature;

    /**
     * 所属的模块
     */
    target?: any;

    /**
     * 初始化特性列表
     */
    initFeatures?(targetOject: IFeatureSupport): Promise<any> {
        return undefined;
    }

    /**
     * 获取生效的特性
     */
    getFeature?(uinfo: userToken, ownertype: string, content: string): Promise<feature> {
        return undefined;
    }
}

/**
 * 特性支持
 */
export interface IFeatureSupport {

    /**
     * 特性控制器
     */
    featureController?: baseFeatureController;

}


// 服务消息出入参数据模型
/**
 * 远程请求
 */
@addon("远程请求", "远程请求,包含：服务名称、方法名称、请求参数", moduleName)
export class remoteRequest extends baseObject {
    serviceName: string;
    functionName: string;
    header?: remoteHeader;
    args?: any;
}

/**
 * 返回消息
 */
interface RtnMsg {
    /** 
     * 代码,具体业务代码值 
     */
    code: string;
    /** 
     * 消息
     */
    message: string;
    /**
     * 原因
     */
    reason: string;
}

/**
 * 基础服务消息头
 */
export abstract class BaseMessageHeader extends baseObject {
    /**
     * 事务ID
     */
    tranID: string = newGuid();
    /**
     * 事务时间
     */
    tranTime: string = getCurrentTimeString();
    /**
     * 用户令牌
     */
    userToken: userToken;
    /**
     * 扩展对象
     */
    expand: any = {};
}

/**
 * 服务请求消息头
 */
@addon("服务请求消息头", "服务请求消息头", moduleName)
export class RequestMessageHeader extends BaseMessageHeader {

}

/**
 * 服务响应消息头
 */
@addon("服务响应消息头", "服务响应消息头", moduleName)
export class ResponseMessageHeader extends BaseMessageHeader {
    /**
     * 返回代码，0 成功， 1 失败
     */
    rtnCode: string = "0";
    /**
     * 返回消息
     */
    rtnMsg: RtnMsg = { code: "", message: "", reason: "" };
}

/**
 * 基础服务消息数据
 */
export abstract class BaseMessage<T, H> extends baseObject {
    /**
     * 头部
     */
    header: H;
    /**
     * 内容
     */
    body: T;

    /**
     * 构造方法
     */
    constructor() {
        super();
        this.init();
    }

    /**
     * 初始化
     */
    protected abstract init();
}

/**
 * 服务请求消息数据
 */
@addon("服务请求消息数据", "服务请求消息数据", moduleName)
export class RequestMessage<T> extends BaseMessage<T, RequestMessageHeader> {
    /**
     * 构造方法
     */
    constructor() {
        super();
    }

    /**
     * 初始化
     */
    protected init() {
        this.header = new RequestMessageHeader();
    }
}

/**
 * 服务响应消息数据
 */
@addon("服务响应消息数据", "服务响应消息数据", moduleName)
export class ResponseMessage<T> extends BaseMessage<T, ResponseMessageHeader> {
    /**
     * 构造方法
     */
    constructor() {
        super();
    }

    /**
     * 初始化
     */
    protected init() {
        this.header = new ResponseMessageHeader();
    }
}
